package com.hanson.controller;

import com.hanson.common.bean.WechatRefundApiResult;
import com.hanson.common.bean.WeiXinConfig;
import com.hanson.common.exception.BusinessException;
import com.hanson.common.service.RedisService;
import com.hanson.common.util.BusinessUtil;
import com.hanson.common.util.WeChatUtils;
import com.hanson.common.util.XmlUtil;
import com.hanson.entity.UserBean;
import com.hanson.service.PayService;
import com.hanson.service.UserService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

@Slf4j
@Controller
@RequestMapping("/weixin")
public class WinXinController {
    @Autowired
    private WxMpService wxMpService;
    @Autowired
    private UserService userService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private PayService payService;
    @Autowired
    private WeiXinConfig weiXinConfig;


    @RequestMapping(value = "/auth", method = RequestMethod.GET)
    public void auth(@RequestParam("code") String code,
                     @RequestParam("state") String returnUrl, HttpServletResponse response) {
        long time1 = System.currentTimeMillis();
        //通过code获取网页授权
        try {
            WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
            WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
            UserBean userBean = userService.selectByOpenId(wxMpUser.getOpenId());
            if (null == userBean) {
                userService.addUser(wxMpUser);
            }
            Cookie userCookie = new Cookie("openId", wxMpUser.getOpenId());
            //存活期1周
            userCookie.setMaxAge(60 * 60 * 24);
            userCookie.setPath("/");
            response.addCookie(userCookie);
            response.sendRedirect(weiXinConfig.getDomian() + returnUrl);
            long time2 = System.currentTimeMillis();
            log.error("【微信网页授权 花费时间：{}】", time2 - time1);
        } catch (WxErrorException e) {
            log.error("【微信网页授权】{}", e);
            throw new BusinessException(e.getError().getErrorMsg());
        } catch (IOException e) {
            log.error("【微信网页授权】{}", e);
        }
    }

    @RequestMapping(value = "/unifiedOrder/{orderSeq}", method = RequestMethod.GET)
    public String unifiedOrder(HttpServletRequest request, @PathVariable String orderSeq, @CookieValue("openId") String openId, ModelMap modelMap) {
        try {
            String orderType = orderSeq.substring(orderSeq.length() - 1, orderSeq.length());
            modelMap.put("orderType", Integer.parseInt(orderType));
            modelMap.put("orderSeq", orderSeq);
            modelMap.put("orderTime", BusinessUtil.date2TimeStr(new Date(), "yyyy-MM-dd HH:mm:ss"));
            modelMap.put("totalFee", "0.0");
            Map<String, Object> map = new HashMap<>();
            map.put("openId", openId);//用户标识openId
            map.put("remoteIp", request.getRemoteAddr());//请求Ip地址
            Map<String, Object> resultMap = payService.unifiedOrder(map, orderSeq, modelMap);
            // 响应报文
            String return_code = String.valueOf(resultMap.get("return_code"));
            String return_msg = String.valueOf(resultMap.get("return_msg"));
            if (return_code.equalsIgnoreCase("FAIL")) {
                modelMap.put("msg", return_msg);
                return "web/payFail";
            } else if (return_code.equalsIgnoreCase("SUCCESS")) {
                // 返回数据
                String result_code = String.valueOf(resultMap.get("result_code"));
                String err_code_des = String.valueOf(resultMap.get("err_code_des"));
                if (result_code.equalsIgnoreCase("FAIL")) {
                    modelMap.put("msg", err_code_des);
                    return "web/payFail";
                } else if (result_code.equalsIgnoreCase("SUCCESS")) {
                    SortedMap<String, Object> returnMap = new TreeMap<>();
                    returnMap.put("timeStamp", BusinessUtil.date2TimeStr(new Date(), "yyyyMMddHHmmss"));
                    returnMap.put("appId", String.valueOf(resultMap.get("appid")));
                    returnMap.put("nonceStr", String.valueOf(resultMap.get("nonce_str")));
                    returnMap.put("package", "prepay_id=" + String.valueOf(resultMap.get("prepay_id")));
                    returnMap.put("signType", "MD5");
                    returnMap.put("paySign", WeChatUtils.createSign(returnMap, weiXinConfig.getPaySignKey()));

                    modelMap.put("timeStamp", returnMap.get("timeStamp"));
                    modelMap.put("appId", returnMap.get("appId"));
                    modelMap.put("nonceStr", returnMap.get("nonceStr"));
                    modelMap.put("package", returnMap.get("package"));
                    modelMap.put("signType", "MD5");
                    modelMap.put("openId", openId);
                    modelMap.put("paySign", returnMap.get("paySign"));
                    return "web/h5Pay";
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            modelMap.put("msg", e.getMessage());
        }
        return "web/payFail";
    }

    @RequestMapping(value = "/notify", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public void notify(HttpServletRequest request, HttpServletResponse response) {
        try {
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
            response.setHeader("Access-Control-Allow-Origin", "*");
            InputStream in = request.getInputStream();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.close();
            in.close();
            //xml数据
            String reponseXml = new String(out.toByteArray(), "utf-8");
            log.info("【notify resp: {}】", reponseXml);
            WechatRefundApiResult result = (WechatRefundApiResult) XmlUtil.xmlStrToBean(reponseXml, WechatRefundApiResult.class);
            String result_code = result.getResult_code();
            if (result_code.equalsIgnoreCase("FAIL")) {
                //订单编号
                String out_trade_no = result.getOut_trade_no();
                log.error("【ERROR:订单 {}支付失败】", out_trade_no);
                response.getWriter().write(setXml("SUCCESS", "OK"));
            } else if (result_code.equalsIgnoreCase("SUCCESS")) {
                //订单编号
                String out_trade_no = result.getOut_trade_no();
                payService.dealNotify(result);
                int totalFee = Integer.parseInt(result.getTotal_fee());
                if(totalFee > 10000000 && StringUtils.isNotEmpty(weiXinConfig.getTemplatePaySuccess())){
                    String orderSeq = result.getOut_trade_no();
                    String orderType = orderSeq.substring(orderSeq.length() - 1, orderSeq.length());
                    String url = null;
                    String remark = null;
                    if("1".equals(orderType)){
                        url = String.format("%s/web/orderDetail/%s",weiXinConfig.getDomian(),orderSeq);
                        remark  = "您的商品购买成功，点击查看详情！";
                    }else if("2".equals(orderType)){
                        url = String.format("%s/web/applyResult/1",weiXinConfig.getDomian());
                        remark = "付款成功，您已经成为VIP";
                    }else if("3".equals(orderType)){
                        url = String.format("%s/web/applyResult/2",weiXinConfig.getDomian());
                        remark = "付款成功，您已经成为合伙人";
                    }
                    // 发送模板消息接口
                    WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                            // 接收者openid
                            .toUser(result.getOpenid())
                            // 模板id
                            .templateId(weiXinConfig.getTemplatePaySuccess())
                            // 模板跳转链接
                            .url(url)
                            .build();
                    // 添加模板数据
                    templateMessage.addData(new WxMpTemplateData("first", "尊敬的客户，您已支付成功"))
                            .addData(new WxMpTemplateData("keyword1", BusinessUtil.getWebAmount(totalFee)))
                            .addData(new WxMpTemplateData("keyword2", orderSeq))
                            .addData(new WxMpTemplateData("remark", remark, "#000000"));
                    String msgId = null;
                    try {
                        // 发送模板消息
                        msgId = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
                    } catch (WxErrorException e) {
                        e.printStackTrace();
                    }
                }
                log.info("订单 {} 支付成功", out_trade_no);
                response.getWriter().write(setXml("SUCCESS", "OK"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
    }

    public static String setXml(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
    }
}
